package client_tree;

import java.awt.Color;
import java.awt.Component;
import java.awt.event.ActionEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;

import javax.swing.JTree;
import javax.swing.SwingUtilities;
import javax.swing.event.TreeSelectionEvent;
import javax.swing.event.TreeSelectionListener;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.TreeSelectionModel;

import utils.Constants;
import client_gui.ClientWindow;

/**
 * Klasa koja predstavlja stablo svih korisnik (online i offline). Implementira interfejs
 * TreeSelectionListener, sto omogucava pracenje dogadjaja pri kliku na cvor stabla.
 * 
 * @author UrosKrkic & Radivoje Popovic
 */
public class ContactsTree extends JTree implements TreeSelectionListener, Constants {

	/**
	 * Vlasnik - glavni prozor aplikacije.
	 */
	private ClientWindow owner = null;
	
 
	/**
	 * TreeModel za stablo.
	 */
	private ContactsTreeModel contactsTreeModel = null;
	
	
	/**
	 * TreeNodeCellRenderer za stablo.
	 */
	private ContactsTreeNodeCellRenderer renderer = null;

	
	/**
	 * ROOT cvor.
	 */
	private RootNode root;

 
	/**
	 * online cvor
	 */
	private ClientModelNode onlineModel = null;
	
 
	/**
	 * offline cvor
	 */
	private ClientModelNode offlineModel = null;
	
	
	/**
	 * boja stabla
	 */
	private Color treeColor = new Color(240, 248, 255);
	
	
	
	/**
	 * Konstruktor.
	 * @param clientModel - model iz koga se uzimaju podaci
	 * @author UrosKrkic & Radivoje Popovic
	 */
	public ContactsTree(ClientWindow owner, ClientModel clientModel) {

		this.owner = owner;
		
		this.onlineModel = clientModel.getOnlineModel();
		this.offlineModel = clientModel.getOfflineModel();
		
		contactsTreeModel = new ContactsTreeModel();
		renderer = new ContactsTreeNodeCellRenderer(this.owner, treeColor);
		
		
		initializeTree();
	}
	

	/**
	 * Metoda vrsi inicijalizaciju stabla.
	 * @author UrosKrkic & Radivoje Popovic
	 */
	private void initializeTree() {

		this.setModel(contactsTreeModel);
		this.setCellRenderer(renderer);
						
		this.getSelectionModel().setSelectionMode(TreeSelectionModel.SINGLE_TREE_SELECTION);

		this.addTreeSelectionListener(this);
		this.addMouseListener(mouseListener);
		
		this.setBackground(treeColor);
		
		this.setRootVisible(false);
		this.setShowsRootHandles(true);
		
		this.setOpaque(true);
		
//		putClientProperty("JTree.lineStyle", "Horizontal");
		
		root = (RootNode) getModel().getRoot();

		root.addClientModel(onlineModel);
		root.addClientModel(offlineModel);
	}

	
	/**
	 * Metoda vrsi osvezavanje stabla (viewer-a)
	 * @author UrosKrkic & Radivoje Popovic
	 */
	public void refreshTree() {
		SwingUtilities.invokeLater(new Runnable() {
			@Override
			public void run() {
				SwingUtilities.updateComponentTreeUI(ContactsTree.this);
			}
		});
	
		this.clearSelection();
	}
	
	
	
	/**
	 * Predstavlja selektovanog korisika u stablu sa korisnicima.
	 */
	private User selectedUser = null;
	
	
	/**
	 * Metod vraca referencu na selektovanog korisnika.
	 * @return - selektovani korisnik
	 * @author UrosKrkic & Radivoje Popovic
	 */
	public User getSelectedUser() {
		return this.selectedUser;
	}
	
	
	/**
	 * Metod eksterno setuje selektovanog korisnika.
	 * Koristi se u BlockList-i, kako bi se iskoristio isti mehanizem akcije za
	 * deblokiranje korisnika, koji se zasniva na selektovanom korisniku iz stabla
	 * sa korisnicima.
	 * @param user - selektovani korisnik koji se setuje
	 * @author UrosKrkic & Radivoje Popovic
	 */
	public void setSelectedUser(User user) {
		this.selectedUser = user;
	}
	
	
	/**
	 * Metoda iz TreeSelectionListener-a. Obradjuje dogadjaje selekcije (klika) odgovarajuceg
	 * cvora stabla.
	 * @author UrosKrkic & Radivoje Popovic
	 */
	public void valueChanged(TreeSelectionEvent e) {
		DefaultMutableTreeNode node = (DefaultMutableTreeNode) this.getLastSelectedPathComponent();
		
		if ( !(node instanceof User) ) {
			owner.getActionManager().setOnOffLineRights(true);
			return;
		}
		
		owner.getActionManager().setOnOffLineRights(false);
		
		User user = (User)node.getUserObject();
		
		selectedUser = user;
		
		// Zabranjuje blokiranje vec blokiranog korisnika, kao i deblokiranje
		// deblokiranog korisnika.
		if (owner.getApplicaton().getClientUser().isBlocked(user.getUsername()) == true) {
			owner.getActionManager().setBlockedRights(true);
		}
		else {
			owner.getActionManager().setBlockedRights(false);
		}
		
		// Zabranjuje se SEND akcija za offline korisnike.
		if ( ((ClientModelNode)user.getParent()).getName().equals("Offline") ) {
			owner.getActionManager().setSendRights(false);
		}

		if ( ((ClientModelNode)user.getParent()).getName().equals("Online") ) {
			owner.getActionManager().setSendRights(true);
		}
	}
	

	
	/**
	 * Anonimna klasa koja rukuje dogadjajima misa. Osliuskivac dogadjaja je JTree objekat,
	 * tj. ContactsTree objekat. Klasa omogucava prikazivanje razlicitih kontekstnih menija,
	 * u zavisnosti od izabranog objketa u JTree hijerarhiji.
	 * @author UrosKrkic & Radivoje Popovic
	 */
	private MouseListener mouseListener = new MouseAdapter() {
		public void mouseReleased(MouseEvent e) {
			if ( e.isPopupTrigger() ) {
				
				DefaultMutableTreeNode node = (DefaultMutableTreeNode) ContactsTree.this.getLastSelectedPathComponent();
				
				if (node instanceof User) {

					owner.getContexMenu().show((Component)e.getSource(),e.getX(),e.getY());
					
				} else
				if (node instanceof ClientModelNode) {

				}
				
				return;		// izlazak iz metode mouseReleased()
			}
			
			
			if ( e.getClickCount() == 2 ) {
				
				if ( owner.getActionManager().getSendMessageAction().isEnabled() == true ) {
					ActionEvent sendMsgEvent = new ActionEvent(ContactsTree.class, 0, "send_msg");
					owner.getActionManager().getSendMessageAction().actionPerformed(sendMsgEvent);
				}
				
				return;
			}
		}
		
		
	};
	
}
